package myLoger

//主文件 定义了一个日志库
import (
	"fmt"
	"runtime"
	"time"
)

//LogLevel  日志等级常量
type LogLevel int

const (
	Info LogLevel = iota //数字越大越严重
	Warning
	Error
)

// outputMode 定义一个输出接口，输出到文件和输出到控制台两个结构体都会实现这个接口的output方法
type outputMode interface {
	output(logger *Logger, curTime string, file string, line int)
}

// Logger  日志类型
type Logger struct {
	curLogLevel   LogLevel   //错误等级
	logStartLevel LogLevel   //设置监控等级，大于这个等级的日志才会输出
	curOutputMode outputMode //输出的方式（输出到文件、输出到控制台）
}

// parseLogger  将日志等级（LogLevel）常量转化为字符串
func parse(l LogLevel) string {
	var res string
	switch l {
	case Info:
		res = "Info"
	case Warning:
		res = "Warning"
	case Error:
		res = "Error"
	default:
		res = "Unkonow"
	}
	return res
}

// NewLoger  日志类型（Logger）的构造函数
// logStartLevel  表示输出日志的起始等级，大于这等级的错误才会输出
// outputMode 表示输出方式
func NewLoger(logStartLevel LogLevel, outputMode outputMode) *Logger {
	return &Logger{
		logStartLevel: logStartLevel,
		curOutputMode: outputMode,
	}
}

// enable 是否启用日志
func (l *Logger) enable(level LogLevel) bool {
	return l.curLogLevel >= l.logStartLevel
}

//dealLog  3个日志处理方法的统一处理函数
func dealLog(skip int, logger *Logger) {
	_, file, line, ok := runtime.Caller(skip)
	if !ok {
		fmt.Printf("追踪调用栈失败")
		return
	}
	curTime := time.Now().Format("2006-01-02 15:04:05")
	logger.curOutputMode.output(logger, curTime, file, line)
	//fmt.Printf("[错误等级：%v] [触发时间:%v] [错误位置:<文件：%v> <行号：%v>] \n", parse(logger.curLogLevel), curTime, file, line)
}

// Info  Info方法
func (l *Logger) Info() {
	l.curLogLevel = Info
	if l.enable(Info) {
		dealLog(2, l)
	}
}

//Warning  Warning方法
func (l *Logger) Warning() {
	l.curLogLevel = Warning
	if l.enable(Warning) {
		dealLog(2, l)
	}
}

//Error  Error方法
func (l *Logger) Error() {
	l.curLogLevel = Error
	if l.enable(Error) {
		dealLog(2, l)
	}
}
